using System;
using System.IO;
using System.Security.Principal;
using System.Threading;
using System.Collections;
using System.Web;
using System.Web.Mail;
using System.Web.Security;
using newtelligence.DasBlog.Web.Core;
using newtelligence.DasBlog.Runtime;
using newtelligence.DasBlog.Web.Services;

namespace newtelligence.DasBlog.Web
{
	/// <summary>
	/// Summary description for Global.
	/// </summary>
	public class Global : HttpApplication
	{
		private XSSUpstreamer xssUpstreamer = null;
		private Thread xssUpstreamerThread = null;
		private MailToWeblog mailToWeblog = null;
		private Thread mailToWeblogThread = null;

		public Global()
		{
			InitializeComponent();
		}

		protected void Application_Start(Object sender, EventArgs e)
		{
			//We clear out the Cache on App Restart...
			IDictionaryEnumerator CacheEnum = HttpRuntime.Cache.GetEnumerator();
			if (CacheEnum != null)
			{
				while (CacheEnum.MoveNext())
				{
					string key = CacheEnum.Key as String;
					if (key != null)
						HttpRuntime.Cache.Remove(key); 
				}
			}

			ILoggingDataService loggingService = null;

			loggingService = LoggingDataServiceFactory.GetService(SiteConfig.GetLogPathFromCurrentContext());
			loggingService.AddEvent(new EventDataItem(EventCodes.ApplicationStartup, "", ""));

			SiteConfig siteConfig = SiteConfig.GetSiteConfig(SiteConfig.GetConfigFilePathFromCurrentContext());

			if (siteConfig.EnablePop3)
			{
				mailToWeblog = new MailToWeblog(
					SiteConfig.GetConfigFilePathFromCurrentContext(),
					SiteConfig.GetContentPathFromCurrentContext(),
					SiteConfig.GetBinariesPathFromCurrentContext(),
					SiteConfig.GetLogPathFromCurrentContext(),
					new Uri(new Uri(SiteConfig.GetSiteConfig().Root), SiteConfig.GetSiteConfig().BinariesDir)
					);

				mailToWeblogThread = new Thread(new ThreadStart(mailToWeblog.Run));
				mailToWeblogThread.Name = "MailToWeblog";
				mailToWeblogThread.IsBackground = true;
				mailToWeblogThread.Start();
			}

			if (siteConfig.EnableXSSUpstream)
			{
				xssUpstreamer = new XSSUpstreamer(
					SiteConfig.GetConfigFilePathFromCurrentContext(),
					SiteConfig.GetContentPathFromCurrentContext(),
					SiteConfig.GetLogPathFromCurrentContext()
					);

				xssUpstreamerThread = new Thread(new ThreadStart(xssUpstreamer.Run));
				xssUpstreamerThread.Name = "XSSUpstreamer";
				xssUpstreamerThread.IsBackground = true;
				xssUpstreamerThread.Start();
			}

			if (siteConfig.EnableMovableTypeBlackList)
			{
				ReferralBlackListFactory.AddBlacklist(new MovableTypeBlacklist(), Path.Combine(SiteConfig.GetConfigPathFromCurrentContext(), "blacklist.txt"));
			}

			if (siteConfig.EnableReferralUrlBlackList && siteConfig.ReferralUrlBlackList.Length != 0)
			{
				ReferralBlackListFactory.AddBlacklist(new ReferralUrlBlacklist(), siteConfig.ReferralUrlBlackList);
			}
		}

		protected void Session_Start(Object sender, EventArgs e)
		{
		}

		protected void Application_BeginRequest(Object sender, EventArgs e)
		{
		}

		protected void Application_EndRequest(Object sender, EventArgs e)
		{
		}

		protected void Application_AuthenticateRequest(Object sender, EventArgs e)
		{
			if (Request.IsAuthenticated == true)
			{
				string role = null;

				// Create the roles cookie if it doesn't exist yet for this session.
				if ((Request.Cookies["portalroles"] == null) || (Request.Cookies["portalroles"].Value == ""))
				{
					// Get roles from UserRoles table, and add to cookie
					UserToken token = SiteSecurity.GetToken(User.Identity.Name);
					if (token != null)
					{
						role = token.Role;

						// Create a cookie authentication ticket.
						FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
							1, // version
							Context.User.Identity.Name, // user name
							DateTime.Now.ToUniversalTime(), // issue time
							DateTime.Now.ToUniversalTime().AddHours(1), // expires every hour
							false, // don't persist cookie
							role // roles
							);

						// Encrypt the ticket
						String cookieStr = FormsAuthentication.Encrypt(ticket);

						// Send the cookie to the client
						Response.Cookies["portalroles"].Value = cookieStr;
						Response.Cookies["portalroles"].Path = "/";
						Response.Cookies["portalroles"].Expires = DateTime.Now.ToUniversalTime().AddHours(1);
					}
					else
					{
						// This is hit for the case where the user
						// has a cookie that points to an out of date
						// user name. Basically we have to un-authenticate
						// and redirect... 
						//

						// Log User Off from Cookie Authentication System
						FormsAuthentication.SignOut();

						// Invalidate roles token
						Response.Cookies["portalroles"].Value = null;
						Response.Cookies["portalroles"].Expires = new DateTime(1999, 10, 12);
						Response.Cookies["portalroles"].Path = "/";
					}
				}
				else
				{
					// OmarS: if you have more than one copy of dasBlog per domain
					// then the application will fail here decrypting the cookie
					// instead expire the existing cookie.
					try
					{
						// Get roles from roles cookie
						FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies["portalroles"].Value);
						role = ticket.UserData;
					}
					catch
					{
						FormsAuthentication.SignOut();

						// Invalidate roles token
						Response.Cookies["portalroles"].Value = null;
						Response.Cookies["portalroles"].Expires = DateTime.MinValue;
						Response.Cookies["portalroles"].Path = "/";
					}
				}

				// Add our own custom principal to the request containing the roles in the auth ticket
				Context.User = new GenericPrincipal(Context.User.Identity, new string[] {role});
			}
		}

		protected void Application_Error(Object sender, EventArgs e)
		{
		}

		protected void Session_End(Object sender, EventArgs e)
		{
		}

		protected void Application_End(Object sender, EventArgs e)
		{
			if (mailToWeblogThread != null)
			{
				mailToWeblogThread.Abort();
				mailToWeblogThread.Join();
			}
			if (xssUpstreamerThread != null)
			{
				xssUpstreamerThread.Abort();
				xssUpstreamerThread.Join();
			}
		}

		#region Web Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// Global
			// 
			this.BeginRequest += new EventHandler(this.Application_BeginRequest);
			this.Error += new EventHandler(this.Application_Error);
			this.AuthenticateRequest += new EventHandler(this.Application_AuthenticateRequest);
			this.EndRequest += new EventHandler(this.Application_EndRequest);

		}

		#endregion
	}
}